/**
 * 
 */
package xj.toolkit.util;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import com.google.common.base.Preconditions;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 
 * @author hp
 * 
 */
public class SimpleRegistry {
	
	static final Logger logger = LoggerFactory.getLogger(SimpleRegistry.class);
	
	private ConcurrentMap<String, Object> registry = new ConcurrentHashMap<String, Object>();

	public Object getOrCreateEntry(String key, Object defaultValue) {
		Object value = registry.putIfAbsent(key, defaultValue);

		return null == value ? defaultValue : value;
	}
	
	public Object getEntry(String key) {
		return registry.get(key);
	}

	public Runnable createEntryRemover(final String key) {
		return new Runnable() {

			public void run() {
				registry.remove(key);
			}
		};
	}

	public Map<String, String> getAllEntries() {
		Map<String, String> ret = new HashMap<String, String>();
		for (Map.Entry<String, Object> entry : this.registry.entrySet()) {
			ret.put(entry.getKey(), entry.getValue().toString());
		}

		return ret;
	}

	public Object setImplToProxy(String key, Class<?>[] intf, Object impl) {
		Preconditions.checkArgument(StringUtils.isNoneBlank(key));
		@SuppressWarnings("unchecked")
		ProxyBuilder<?> builder = (ProxyBuilder<?>) getOrCreateEntry(key, new ProxyBuilder(intf));

		builder.setImpl(impl);
		
		return impl;
	}
	
	@SuppressWarnings("unchecked")
	public <T> Object setImplToProxy(String key, Class<T> intf, T impl) {
		Preconditions.checkArgument(StringUtils.isNoneBlank(key));
		ProxyBuilder<T> builder = (ProxyBuilder<T>) getOrCreateEntry(key, new ProxyBuilder<T>(intf));

		builder.setImpl(impl);
		return impl;
	}

	public <T> Object getProxyOf(String key, Class<T> intf) {
		Preconditions.checkArgument(StringUtils.isNoneBlank(key));
		
		ProxyBuilder<T> defaultBuilder = (intf == null ? null : new ProxyBuilder<T>(intf));
		@SuppressWarnings("unchecked")
		ProxyBuilder<T> builder = (ProxyBuilder<T>) getOrCreateEntry(key, defaultBuilder);
		if (builder == null) {
			return null;
		}
		Object proxy = builder.buildProxy();
		return proxy;
	}

	@SuppressWarnings("unchecked")
	public <T> Object getProxyOf(String key, Class<T>[] intf) {
		Preconditions.checkArgument(StringUtils.isNoneBlank(key));
		
		ProxyBuilder<T> defaultBuilder = (intf == null ? null : new ProxyBuilder<T>(intf));

		ProxyBuilder<T> builder = (ProxyBuilder<T>) getOrCreateEntry(key, defaultBuilder);
		if (builder == null) {
			return null;
		}
		Object proxy = builder.buildProxy();
		return proxy;
	}

	@SuppressWarnings("unchecked")
	public <T> Object getProxyOf(String key) {
		Preconditions.checkArgument(StringUtils.isNoneBlank(key));
		ProxyBuilder<T> builder = (ProxyBuilder<T>) getOrCreateEntry(key, null);
		if (builder == null) {
			return null;
		}
		Object proxy = builder.buildProxy();
		return proxy;
	}

}
